home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1994 November / Cd Ware (Nro. 2) - Epimundo.iso / DOS / PG / COMBOX.ZIP / STRLIB.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-04-11  |  21.7 KB  |  698 lines

  1. Unit Strlib;
  2.  
  3. Interface
  4.  
  5. {uses
  6.    Global,dos, LanGlob ;}
  7.  
  8. type
  9.    StrPtr = ^string;
  10.    AsciizType = array [ 0..255 ] of char;
  11.  
  12. procedure StrAddRight ( var TheStr : string ; SubStr : string ;
  13.                             TheStrLimit : byte ) ;
  14. procedure StrAddLeft ( SubStr : string ; var TheStr : string ;
  15.                        TheStrLimit : byte ) ;
  16. Function NewStr    ( S : string ) : StrPtr;
  17. Function UpCaseStr ( S : string ) : string;
  18. Function LRTrim    ( S : string ) : string;
  19. Function LTrim     ( S : string ) : string;
  20. Function RTrim     ( S : string ) : string;
  21. Function LPad      ( S : string; Len : byte ) : string;
  22. Function RPad      ( S : string; Len : byte ) : string;
  23. Function CenterStr ( S : string; Width : byte ) : string;
  24. Function StrToInt  ( S : string ) : longint;
  25. Function IntToStr  ( I : longint ) : string;
  26. Function RealToStr ( I : real; Digits, Decimals : integer ) : string;
  27. Function StrToReal ( S : string; Digits, Decimals : integer  ) : real;
  28. Function NumStr    ( S : string; Width : byte ) : string;
  29. Function Spaces    ( Width : integer ) : string;
  30. Function FillStr   ( Attr : char ; Size : byte ) : string ;
  31. Function FillLine  ( WIdth : byte; First, Middle, Last : char ) : string;
  32. Function ChFreq ( Ch : char; S : string ) : integer;
  33. Function RPos ( Ch : char; S : string ) : integer;
  34. Function StrToMask ( S : string; Mask : string ) : string;
  35. Function StripMask ( S : string ) : string;
  36.  
  37. Procedure DisposeString ( StringPtr : StrPtr );
  38. Procedure StrToAsciiz   ( S : string; var Asciiz : AsciizType );
  39. Procedure AsciizToStr   ( Asciiz : AsciizType; var S : string );
  40.  
  41. Implementation
  42.  
  43. {========================================================================}
  44.  
  45. Function RPos ( Ch : char; S : string ) : integer;
  46.  
  47. var
  48.    i : byte;
  49.    Found : boolean;
  50.  
  51. Begin
  52.    Found := false;
  53.    i := length ( S ) + 1;
  54.    while ( not Found ) and ( i > 0 ) do
  55.       begin
  56.       dec ( i );
  57.       if S [ i ] = Ch then
  58.          Found := true;
  59.       end;
  60.    RPos := i;
  61. End;
  62.  
  63. {========================================================================}
  64.  
  65. Function ChFreq ( Ch : char; S : string ) : integer;
  66.  
  67. var
  68.    i, Count : byte;
  69.  
  70. Begin
  71.    Count := 0;
  72.    for i := 1 to length ( S ) do
  73.       if S [ i ] = Ch then
  74.          inc ( Count );
  75.    ChFreq := Count;
  76. End;
  77.  
  78. {========================================================================}
  79.  
  80. procedure StrAddRight ( var TheStr : string ; SubStr : string ;
  81.                             TheStrLimit : byte ) ; assembler ;
  82.  
  83.   { FAST string concatenator }
  84.   { Almost 6 times faster than to say TheStr := TheStr + SubStr }
  85.  
  86.   { for passing a string, TheStrLimit should contain 255.     }
  87.   { for passing a stringtype such as, for eg., string [ 10 ], }
  88.   { TheStrLimit should contain 10 so, for safety's sake,      }
  89.   { pass 'sizeof ( TheStr ) - 1' through TheStrLimit          }
  90.  
  91. asm
  92.   mov   dx, ds                    { save data segment                         }
  93.   push  es
  94.   mov   al, TheStrLimit           { store maximum length of string allowed    }
  95.   les   di, TheStr
  96.   mov   bx, es:[di]
  97.   cmp   bl, al                    { is there room left in TheStr to add?      }
  98.   jae   @TheStrFull
  99.   xor   bh, bh
  100.   lds   si, SubStr
  101.   mov   cx, ds:[si]
  102.   or    cl, cl                    { is SubStr null?                           }
  103.   jz    @TheStrFull
  104.   inc   si
  105.   sub   al, bl
  106.   cmp   al, cl                    { is there room to add all of SubStr?       }
  107.   jae   @RoomLeft
  108.   mov   cl, al
  109. @RoomLeft:
  110.   xor   ch, ch
  111.   add   es:[di], cl               { store new length of TheStr                }
  112.   inc   di                        { take the length into account              }
  113.   add   di, bx                    { position to end of TheStr                 }
  114.   cld                             { we are moving forward                     }
  115.   rep   movsb                     { transfer SubStr to TheStr                 }
  116. @TheStrFull:
  117.   pop   es
  118.   mov   ds, dx                    { restore data segment                      }
  119. end ;
  120.  
  121. {=============================================================================}
  122.  
  123. procedure StrAddLeft ( SubStr : string ; var TheStr : string ;
  124.                        TheStrLimit : byte ) ; assembler ;
  125.  
  126.   { FAST string concatenator }
  127.   { More than 2 times faster than to say TheStr := SubStr + TheStr }
  128.  
  129.   { for passing a string, TheStrLimit should contain 255.     }
  130.   { for passing a stringtype such as, for eg., string [ 10 ], }
  131.   { TheStrLimit should contain 10 so for safety's sake        }
  132.   { pass 'sizeof ( TheStr ) - 1' through TheStrLimit          }
  133.  
  134. asm
  135.   push  ds                        { save data segment                         }
  136.   push  es
  137.   mov   al, TheStrLimit           { store maximum length of string allowed    }
  138.   les   di, TheStr
  139.   mov   cx, es:[di]
  140.   cmp   cl, al                    { is there room left in TheStr to add?      }
  141.   jae   @TheStrFull
  142.   lds   si, SubStr
  143.   mov   bx, ds:[si]
  144.   or    bl, bl                    { is SubStr null?                           }
  145.   jz    @TheStrFull
  146.   xor   bh, bh
  147.   mov   dx, bx                    { store length for SubStr transfer          }
  148.   sub   al, cl
  149.   cmp   al, bl                    { is there room to add all of SubStr?       }
  150.   jae   @RoomLeft
  151.   mov   bl, al
  152. @RoomLeft:
  153.   add   bl, cl
  154.   mov   es:[di], bl               { store new length of TheStr                }
  155.   add   di, bx                    { position to end of new TheStr             }
  156.   std                             { we are moving backwards                   }
  157.   or    cl, cl                    { is length of TheStr zero?                 }
  158.   jz    @TheStrNull
  159.   xor   ch, ch
  160.   lds   si, TheStr
  161.   add   si, cx                    { position to end of TheStr                 }
  162.   rep   movsb                     { transfer TheStr to TheStr                 }
  163.   lds   si, SubStr
  164. @TheStrNull:
  165.   add   si, dx                    { position to end of SubStr                 }
  166.   mov   cx, dx
  167.   rep   movsb                     { transfer SubStr to TheStr                 }
  168. @TheStrFull:
  169.   pop   es
  170.   pop   ds                        { restore data segment                      }
  171. end ;
  172.  
  173. {=============================================================================}
  174.  
  175. function FillStr ( Attr : char ; Size : byte ) : string ; assembler ;
  176.  
  177. asm
  178.   mov   bx, es
  179.   les   di, @result
  180.   cmp   Size, 0FFh
  181.   jbe   @AssignWidth
  182.   mov   cx, 0FFh
  183.   jmp   NEAR PTR @Continue
  184. @AssignWidth:
  185.   mov   cl, Size
  186.   xor   ch, ch
  187. @Continue:
  188.   mov   es:[di], cl
  189.   inc   di
  190.   cld
  191.   mov   al, Attr
  192.   rep   stosb
  193.   mov   es, bx
  194. end ;
  195.  
  196. {========================================================================}
  197.  
  198. Function FillLine ( Width : byte; First, Middle, Last : char ) : string; assembler;
  199.  
  200. asm
  201.    mov   bx, es
  202.    les   di, @result               { load destination register             }
  203.    cld                             { we are moving forward                 }
  204.    mov   al, Width                 { move desired width into AL            }
  205.    stosb
  206.    or    al, al
  207.    jz    @DoneString
  208.    xor   ch, ch
  209.    mov   cl, al                    { we only want the low byte             }
  210.    mov   al, First
  211.    stosb                           { string [ 1 ] gets First               }
  212.    dec   cl
  213.    mov   al, Middle
  214. @AllOfString:
  215.    cmp   cl, 1                     { if at string [ TheWidth ] then        }
  216.    je    @AssignLast               { get ready to assign Last              }
  217.    stosb                           { else start assigning Middle to string }
  218.    loop  @AllOfString
  219. @AssignLast:
  220.    mov   al, Last
  221.    stosb                           { string [ TheWidth ] gets Last         }
  222. @DoneString:
  223.    mov   es, bx
  224. end;
  225.  
  226. {========================================================================}
  227.  
  228. Procedure StrToAsciiz ( S : string; var Asciiz : AsciizType );
  229.  
  230. Begin
  231.    move ( S [ 1 ], Asciiz [ 0 ], length ( S ) );
  232.    Asciiz [ succ ( length ( S ) ) ] := #0;
  233. End;
  234.  
  235. {========================================================================}
  236.  
  237. Procedure AsciizToStr ( Asciiz : AsciizType; var S : string );
  238.  
  239. var
  240.    i : byte;
  241.  
  242. Begin
  243.    i := 0;
  244.    while Asciiz [ i ] <> #0 do
  245.       inc ( i );
  246.  
  247.    move ( Asciiz [ 0 ], S [ 1 ], i );
  248.    S [ 0 ] := chr ( i );
  249. End;
  250.  
  251. {========================================================================}
  252.  
  253. Function NewStr ( S : string ) : StrPtr;
  254.  
  255. var
  256.    StringPtr : StrPtr;
  257.  
  258. Begin
  259.    getmem ( StringPtr, succ ( length ( S ) ) );
  260.    StringPtr^ := S;
  261.    NewStr := StringPtr;
  262. End;
  263.  
  264. {========================================================================}
  265.  
  266. Function NumStr ( S : string; Width : byte ) : string;
  267.  
  268. const
  269.   StrSize = sizeof ( string ) - 1;
  270.  
  271. var
  272.    Str1, Str2 : string;
  273.    i : byte;
  274.  
  275. Begin
  276.    Str1 := '';
  277.    Str2 := '';
  278.    for i := length ( S ) downto 1 do
  279.       begin
  280.       if length ( Str1 ) = 3 then
  281.          begin
  282.          StrAddLeft ( ',' + Str1, Str2, StrSize );
  283.          Str1 := ''
  284.          end;
  285.       StrAddLeft ( S [ i ], Str1, StrSize );
  286.       end;
  287.    StrAddLeft ( Str1, Str2, StrSize );
  288.    NumStr := LPad ( Str2, Width );
  289. End;
  290.  
  291. {========================================================================}
  292.  
  293. Procedure DisposeString ( StringPtr : StrPtr );
  294.  
  295. Begin
  296.    freemem ( StringPtr, succ ( length ( StringPtr^ ) ) );
  297. End;
  298.  
  299. {========================================================================}
  300.  
  301. Function CenterStr ( S : string; Width : byte ) : string; assembler;
  302.  
  303. asm
  304.   mov   bx, ds                    { save data segment                      }
  305.   push  es
  306.   lds   si, S                     { load source register with S            }
  307.   les   di, @result               { load destination register with @result }
  308.   cld                             { we are moving forward                  }
  309.   mov   cx, ds:[si]               { move length of S into cx               }
  310.   xor   ch, ch                    { we only want the low byte              }
  311.   mov   ah, Width
  312.   cmp   cl, ah                    { if length of S >= Width then           }
  313.   jae   @AssignAllOfString        { pass S through Center else             }
  314.   inc   si
  315.   mov   al, ah
  316.   stosb                           { resulting length will be the width     }
  317.   sub   ah, cl                    { subtract length of S from width        }
  318.   test  ah, 1
  319.   jz    @NotOdd
  320.   inc   ah
  321. @NotOdd:
  322.   shr   ah, 1                     { divide by 2                            }
  323.   mov   al, ' '                   { store space in AL                      }
  324.   mov   dl, cl                    { store CL in DL                         }
  325.   mov   cl, ah                    { for I := 1 to AH..                     }
  326.   repnz stosb                     { store blank space in Center            }
  327.   mov   cl, dl
  328.   repnz movsb                     { now add string S to Center             }
  329.   add   ah, dl                    { now add length of S to AH              }
  330.   mov   cl, Width
  331.   sub   cl, ah                    { subtract resulting AH from Width       }
  332.   repnz stosb                     { finish off with blank spaces           }
  333.   jmp   NEAR PTR @Finished
  334. @AssignAllOfString:
  335.   inc   cl                        { string has to include zeroth place     }
  336.   repnz movsb
  337. @Finished:
  338.   pop   es
  339.   mov   ds, bx                    { restore                                }
  340. end ;
  341.  
  342. {========================================================================}
  343.  
  344. Function UpCaseStr ( S : string ) : string; assembler;
  345.  
  346. asm
  347.   mov   bx, ds                    { save data segment                       }
  348.   mov   dx, es
  349.   lds   si, S                     { load source register with S             }
  350.   les   di, @result               { load destination register               }
  351.   cld                             { we are moving forward                   }
  352.   movsb                           { resulting length will be the same       }
  353.   mov   cx, ds:[si-1]             { move length of S into cx                }
  354.   or    cl, cl                    { is it a zero?                           }
  355.   jz    @IsNullString
  356.   xor   ch, ch                    { we only want the low byte               }
  357. @AllOfString:
  358.   lodsb
  359.   cmp   al, 'a'
  360.   jb    @NextChar                 { if lower than 'a', read next character  }
  361.   cmp   al, 'z'
  362.   ja    @NextChar                 { if higher than 'z', read next character }
  363.   sub   al, 'a' - 'A'             { else uppercase the character.           }
  364. @NextChar:
  365.   stosb                           { store source character to destination   }
  366.   loop  @AllOfString
  367. @IsNullString:
  368.   mov   es, dx
  369.   mov   ds, bx                    { restore                                 }
  370. end ;
  371.  
  372. {========================================================================}
  373.  
  374. Function Spaces ( Width : integer ) : string; assembler;
  375.  
  376. asm    { function Spaces }
  377.   push  es
  378.   les   di, @RESULT
  379.   cmp   Width, 0FFh
  380.   jbe   @AssignWidth
  381.   mov   cx, 0FFh
  382.   jmp   NEAR PTR @Continue
  383. @AssignWidth:
  384.   mov   cx, Width
  385. @Continue:
  386.   mov   es:[di], cl
  387.   inc   di
  388.   cld
  389.   mov   al, ' '
  390.   rep   stosb
  391.   pop   es
  392. end ;  { function Spaces }
  393.  
  394. {========================================================================}
  395.  
  396. Function LPad ( S : string; Len : byte ) : string; assembler;
  397.  
  398. asm
  399.   push  ds                        { save data segment                         }
  400.   push  es
  401.   lds   si, S                     { load source register with S               }
  402.   les   di, @result               { load destination register                 }
  403.   cld                             { we are moving forward                     }
  404.   mov   cx, ds:[si]               { move length of S into cx                  }
  405.   xor   ch, ch                    { we only want the low byte                 }
  406.   mov   bl, Len
  407.   inc   si
  408.   mov   al, bl
  409.   stosb                           { resulting length will be Len              }
  410.   cmp   cl, bl                    { if length of S > Len then                 }
  411.   ja    @AssignPartOfString       { pass Len amount of S through PadLeft else }
  412.   sub   bl, cl                    { subtract length of S from Len             }
  413.   mov   al, ' '                   { store space in AL                         }
  414.   mov   dl, cl                    { store CL in DL                            }
  415.   mov   cl, bl                    { for I := 1 to BL..                        }
  416.   repnz stosb                     { store blank space in padded string        }
  417.   mov   cl, dl
  418.   repnz movsb                     { now add string S to padded string         }
  419.   jmp   NEAR PTR @Finished
  420. @AssignPartOfString:
  421.   mov   cl, Len
  422.   repnz movsb
  423. @Finished:
  424.   pop   es
  425.   pop   ds                        { restore                                   }
  426. End;
  427.  
  428. {========================================================================}
  429.  
  430. Function RPad ( S : string; Len : byte ) : string; assembler;
  431.  
  432. asm
  433.   push  ds                        { save data segment                          }
  434.   push  es
  435.   lds   si, S                     { load source register with S                }
  436.   les   di, @result               { load destination register                  }
  437.   cld                             { we are moving forward                      }
  438.   mov   cx, ds:[si]               { move length of S into cx                   }
  439.   xor   ch, ch                    { we only want the low byte                  }
  440.   mov   bl, Len
  441.   inc   si
  442.   mov   al, bl
  443.   stosb                           { resulting length will be Len               }
  444.   cmp   cl, bl                    { if length of S > Len then                  }
  445.   ja    @AssignPartOfString       { pass Len amount of S through PadRight else }
  446.   mov   dl, cl                    { store CL in DL                             }
  447.   repnz movsb                     { add string S to padded string              }
  448.   sub   bl, dl                    { subtract length of S from Len              }
  449.   mov   al, ' '                   { store space in AL                          }
  450.   mov   cl, bl                    { for I := 1 to BL..                         }
  451.   repnz stosb                     { store blank space in padded string         }
  452.   jmp   NEAR PTR @Finished
  453. @AssignPartOfString:
  454.   mov   cl, Len
  455.   repnz movsb
  456. @Finished:
  457.   pop   es
  458.   pop   ds                        { restore                             }
  459. end ;
  460.  
  461. {========================================================================}
  462.  
  463. Function LRTrim ( S : string ) : string; assembler;
  464.  
  465. asm
  466.   mov   bx, ds                    { save data segment                   }
  467.   push  es
  468.   lds   si, S                     { load source register with S         }
  469.   les   di, @result               { load destination register           }
  470.   mov   cl, ds:[si]               { move length of S into cx            }
  471.   or    cl, cl                    { is it a zero?                       }
  472.   jz    @AssignNullString
  473.   xor   ch, ch                    { we only want the low byte           }
  474.   mov   al, ' '                   { store space in AL                   }
  475. @IsSpace:
  476.   inc   si
  477.   cmp   ds:[si], al
  478.   loope @IsSpace                  { keep looping until it's not a blank }
  479.   or    cl, cl
  480.   jnz   @NotBlankString
  481.   cmp   ds:[si], al               { last character could be a non-blank }
  482.   je    @AssignNullString
  483. @NotBlankString:
  484.   inc   cl
  485.   inc   di
  486.   mov   dl, cl                    { store CL in DL                      }
  487.   cld                             { we are moving forward               }
  488.   repnz movsb                     { add string S to trimmed string      }
  489.   dec   di
  490.   mov   cl, dl
  491.   std
  492.   repe  scasb                     { while = to blank space              }
  493.   inc   cl
  494.   les   di, @result               { load destination register           }
  495. @AssignNullString:
  496.   mov   es:[di], cl               { move new length to trimmed string   }
  497.   pop   es
  498.   mov   ds, bx                    { restore                             }
  499. end ;
  500.  
  501. {========================================================================}
  502.  
  503. Function LTrim ( S : string ) : string; assembler;
  504.  
  505. asm    { function TrimLeft }
  506.   push  ds
  507.   lds   si, S
  508.   mov   cl, ds:[si]
  509.   xor   ch, ch
  510.   or    cl, cl
  511.   jz    @AssignString
  512.   mov   al, ' '
  513. @LoopAgain:
  514.   inc   si
  515.   cmp   ds:[si], al
  516.   loope @LoopAgain
  517.   jz    @AssignString  { if last character wasn't a blank.. }
  518.   inc   cl
  519. @AssignString:
  520.   push  es
  521.   les   di, @RESULT
  522.   mov   es:[di], cl
  523.   inc   di
  524.   cld
  525.   rep   movsb
  526.   pop   es
  527.   pop   ds
  528. end ;  { function TrimLeft }
  529.  
  530. {========================================================================}
  531.  
  532. Function RTrim ( S : string ) : string; assembler;
  533.  
  534. asm    { function RTrim }
  535.   push  ds
  536.   lds   si, S
  537.   mov   cl, ds:[si]
  538.   xor   ch, ch
  539.   or    cl, cl
  540.   jz    @AssignString
  541.   mov   bx, cx
  542.   inc   bx             { get ready for decrement in LoopAgain }
  543.   mov   al, ' '
  544. @LoopAgain:
  545.   dec   bx
  546.   cmp   ds:[si+bx], al
  547.   loope @LoopAgain
  548.   jz    @AssignString  { if last character wasn't a blank.. }
  549.   inc   cl
  550.   inc   si
  551. @AssignString:
  552.   push  es
  553.   les   di, @RESULT
  554.   mov   es:[di], cl
  555.   inc   di
  556.   cld
  557.   rep   movsb
  558.   pop   es
  559.   pop   ds
  560. end ;  { function RTrim }
  561.  
  562. {========================================================================}
  563.  
  564. Function StrToInt ( S : string ) : longint;
  565.  
  566. var
  567.    Error : integer;
  568.    Value : longint;
  569.  
  570. Begin
  571.    val ( S, Value, Error );
  572.    StrToInt := Value;
  573. End;
  574.  
  575. {========================================================================}
  576.  
  577. Function IntToStr ( I : longint ) : string;
  578.  
  579. var
  580.    Value : string;
  581.  
  582. Begin
  583.    str ( I ,Value );
  584.    IntToStr := Value;
  585. End;
  586.  
  587. {========================================================================}
  588.  
  589. Function StrToReal ( S : string; Digits, Decimals : integer  ) : real;
  590.  
  591. var
  592.    Error : integer;
  593.    Value : real;
  594.  
  595. Begin
  596.    val ( S, Value, Error );
  597.    if Error = 0 then
  598.       begin
  599.       S := RealToStr ( Value, Digits, Decimals );
  600.       val ( S, Value, Error );
  601.       end;
  602.    StrToReal := Value;
  603. End;
  604.  
  605. {========================================================================}
  606.  
  607. Function RealToStr ( I : real; Digits, Decimals : integer ) : string;
  608.  
  609. var
  610.    Value : string;
  611.  
  612. Begin
  613.    str ( I:Digits:Decimals ,Value );
  614.    RealToStr := Value;
  615. End;
  616.  
  617. {========================================================================}
  618. { This needs work!
  619. Function CleanNumStr ( S : string ) : string;
  620.  
  621. var
  622.    i : integer;
  623.  
  624. Begin
  625.    for i := 1 to length ( S ) do
  626.       if not ( S [ i ] in [ '.', '0'..'9' ] ) then
  627.          Delete ( S, i, 1 );
  628.    CleanNumStr := S;
  629. End;
  630. }
  631. {========================================================================}
  632.  
  633. Function StrToMask ( S : string; Mask : string ) : string;
  634.  
  635. var
  636.    i : integer;
  637.    Negative : boolean;
  638.  
  639. Begin
  640.    S := LRTrim ( S );
  641.    Negative := S [ 1 ] = '-';
  642.    if Negative then
  643.       S := copy ( S, 2, length ( S ) );
  644.  
  645.    { add commas }
  646.    if pos ( ',', Mask ) <> 0 then
  647.       begin
  648.       { calc first comma pos }
  649.       i := pos ( '.', S );
  650.       if i = 0 then
  651.          i := length ( S ) - 2
  652.       else
  653.          dec ( i, 3 );
  654.       while i > 1 do
  655.          begin
  656.          Insert ( ',', S, i );
  657.          dec ( i, 3 );
  658.          end;
  659.       end;
  660.  
  661.    { add a dollar sign }
  662.    if pos ( '$', Mask ) <> 0 then
  663.       S := '$' + S;
  664.  
  665.    { add a percent sign }
  666.    if pos ( '%', Mask ) <> 0 then
  667.       S := S + '%';
  668.  
  669.    { add a minus sign }
  670.    if Negative then
  671.       S := '-' + S;
  672.  
  673.    StrToMask := LPad ( S, length ( Mask ) );
  674. End;
  675.  
  676. {========================================================================}
  677.  
  678. Function StripMask ( S : string ) : string;
  679.  
  680. const
  681.    ValidChars = [ '0'..'9', '.', '-' ];
  682.  
  683. var
  684.    St : string;
  685.    i : integer;
  686.  
  687. Begin
  688.    St := '';
  689.    for i := 1 to length ( S ) do
  690.       if S [ i ] in ValidChars then
  691.          St := St + S [ i ];
  692.    StripMask := St;
  693. End;
  694.  
  695. {=============================================================================}
  696.  
  697. End.
  698.